package com.reconcile.phone.im;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.easemob.im.server.EMException;
import com.easemob.im.server.EMService;
import com.easemob.im.server.model.EMCustomMessage;
import com.easemob.im.server.model.EMKeyValue;
import com.easemob.im.server.model.EMRemoveMember;
import com.easemob.im.server.model.EMSentMessageIds;
import com.easemob.im.server.model.EMTextMessage;
import com.easemob.im.server.model.EMUser;
import com.easemob.push.EMPushService;
import com.easemob.push.model.EMPushHttpResponse;
import com.easemob.push.model.PushMessage;
import com.easemob.push.model.PushRequest;
import com.easemob.push.model.PushStrategy;
import com.reconcile.phone.common.constant.HttpStatus;
import com.reconcile.phone.common.constant.IMConstants;
import com.reconcile.phone.common.constant.UserConstants;
import com.reconcile.phone.common.exception.ServiceException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;

/**
 * 微信相关工具
 *
 * @author zlj
 * @since 2023/3/8
 */
//@Component
@Slf4j
public class IMUtil {

  @Resource
  private EMService service;

  private static EMPushService staticEMPushService;

  private static EMService staticEMService;
  @Resource
  private EMPushService emPushService;

  private static final String USER_NAME_PREFIX = "labor";

  /**
   * 环信Im密码前缀
   */
  private static final String HUANXIN_IM_PASSWORD_PREFIX = "password";

  /**
   * 设置用户属性
   *
   * @param username 用户名
   * @param metadata 要设置的属性
   */
  public static void setMetadataToUser(String username, Map<String, String> metadata) {
    try {
      staticEMService.metadata().setMetadataToUser(username, metadata).block();
    } catch (EMException e) {
      log.error("设置用户属性失败code:{}msg:{}", e.getErrorCode(), e.getMessage());
      throw new ServiceException("设置用户属性失败");
    }
  }

  /**
   * 注册用户
   *
   * @param userId      用户ID
   * @param password    用户密码
   * @param appUserRole 用户角色 {@link UserConstants}
   */
  public static EMUser createUser(Long userId, String password, String appUserRole) {
    try {
      return staticEMService.user().create(appUserRole + userId, HUANXIN_IM_PASSWORD_PREFIX + password).block();
    } catch (EMException e) {
      log.error(String.valueOf(e.getErrorCode()));
      log.error(e.getMessage() + "IM注册失败");
      //throw new ServiceException("IM注册失败");
    }
    return null;
  }

  /**
   * 推送通知消息
   *
   * @param userIds     userId
   * @param title       标题
   * @param content     内容
   * @param subTitle    通知栏展示的通知副标题。该字段长度不能超过 10 个字符。  ios
   * @param ext         推送自定义扩展信息，为自定义 key-value 键值对。键值对个数不能超过 10 且长度不能超过 1024 个字符。  内容
   * @param appUserRole 用户角色 {@link UserConstants}
   * @return 结果
   */
  public static boolean pushNotificationMessages(List<Long> userIds, String title, String content, String subTitle,
                                                 Map<String, Object> ext, String appUserRole) {
    if (ObjectUtil.isEmpty(userIds)) {
      throw new ServiceException("用户id不能为空");
    }

    if (StrUtil.isBlank(subTitle)) {
      subTitle = null;
    }
    //推送特性配置内容，详见：https://docs-im.easemob.com/push/apppush/pushkv
    PushMessage pushMessage = PushMessage.builder()
        .title(title)
        .content(content)
        .subTitle(subTitle)
        .ext(ext)
        //与用户点击通知相关的操作
//            .config(Config.builder()
//                .clickAction(
//                    ClickAction.builder().url("https://www.easemob.com").build()
//                )
//                .badge(
//                    Badge.builder().addNum(1).activity("com.xxx.activity").build()
//                )
//                .build()
//            )
        .build();
    try {
      EMPushHttpResponse single = staticEMPushService.push().single(
          PushRequest.builder()
              .setTargets(userIds.stream().map(userId -> appUserRole + userId).collect(Collectors.toList()))
              .setStrategy(PushStrategy.EASEMOB_CHANNEL)
              .setPushMessage(pushMessage)
              .build()
      );
      int status = single.getStatus();
      if (status == HttpStatus.SUCCESS) {
        return true;
      }

    } catch (Exception e) {
      log.error("推送通知消息失败,msg{}", e.getMessage());
      throw new ServiceException("推送通知消息失败");
    }

    return false;
  }

  /**
   * 给用户发送系统自定义消息
   *
   * @param userIds      用户id
   * @param notification 消息模版
   * @param appUserRole  用户角色 {@link UserConstants}
   * @return 结果
   */
  public static Map<String, String> sendSystemCustomMessageToUser(List<Long> userIds, Notification notification, String appUserRole) {
    if (ObjectUtil.isEmpty(userIds)) {
      throw new ServiceException("用户id不能为空");
    }
    EMCustomMessage emCustomMessage = new EMCustomMessage();
    Set<String> toUsersSet = userIds.stream().map(userId -> appUserRole + userId).collect(Collectors.toSet());
    Map<String, Object> extensions = BeanUtil.beanToMap(notification);
    Map<String, String> messageIdsByEntityId;
    try {
      EMSentMessageIds emSentMessageIds = staticEMService.message()
          .send(IMConstants.FROM_SYSTEM, IMConstants.TO_TYPE_USERS, toUsersSet, emCustomMessage, EMKeyValue.of(extensions)).block();
      assert emSentMessageIds != null;
      messageIdsByEntityId = emSentMessageIds.getMessageIdsByEntityId();
    } catch (EMException e) {

      log.error("发送系统自定义消息失败,code{},msg{}", e.getErrorCode(), e.getMessage());
      //throw new ServiceException("发送系统自定义消息失败");
      return new HashMap<>(1);
    }
    return messageIdsByEntityId;
  }

  /**
   * 给用户发送文本消息
   *
   * @param userIds     用户id
   * @param from        发送者
   * @param text        文本消息
   * @param appUserRole 用户角色 {@link UserConstants}
   * @return 结果
   */
  public static Map<String, String> sendTextMessageToUser(List<Long> userIds, String from, String text, String appUserRole) {
    if (ObjectUtil.isEmpty(userIds)) {
      throw new ServiceException("用户id不能为空");
    }
    EMTextMessage emTextMessage = new EMTextMessage();
    emTextMessage.text(text);
    Set<String> toUsersSet = userIds.stream().map(userId -> appUserRole + userId).collect(Collectors.toSet());

    Map<String, String> messageIdsByEntityId;
    try {
      EMSentMessageIds emSentMessageIds = staticEMService.message()
          .send(from, IMConstants.TO_TYPE_USERS, toUsersSet, emTextMessage, null).block();
      assert emSentMessageIds != null;
      messageIdsByEntityId = emSentMessageIds.getMessageIdsByEntityId();
    } catch (EMException e) {

      log.error("发送消息失败,code{},msg{}", e.getErrorCode(), e.getMessage());
      //throw new ServiceException("发送系统自定义消息失败");
      return new HashMap<>(1);
    }
    return messageIdsByEntityId;
  }


  /**
   * 给群发送系统自定义消息
   *
   * @param groups 群组id
   * @param ext    信息
   */
  public static void sendCustomMessageToChatGroups(List<String> groups, Map<String, Object> ext) {
    Set<String> toGroups = new HashSet<>(groups);
    EMCustomMessage emCustomMessage = new EMCustomMessage();
    Map<String, Object> extensions = BeanUtil.beanToMap(ext);

    try {
      EMSentMessageIds messageIds =
          staticEMService.message().send(null, IMConstants.TO_TYPE_CHATGROUPS, toGroups, emCustomMessage, EMKeyValue.of(extensions))
              .block();
    } catch (EMException e) {
      log.error("给群发送系统自定义消息失败,code{},msg{}", e.getErrorCode(), e.getMessage());
      throw new ServiceException("给群发送系统自定义消息失败");
    }
  }

  /**
   * 创建私有群
   * 私有群无法被搜索到
   *
   * @param owner           群主的用户名  用户id
   * @param groupName       群名，最大长度为 128 字符
   * @param description     群介绍，最大长度为 512 字符
   * @param members         初始群成员的用户名列表 用户id
   * @param maxMembers      群最大成员数
   * @param canMemberInvite 新成员加入需要管理员审批
   * @param custom          群组扩展信息，例如可以给群组添加业务相关的标记，最大长度为 1024 字符
   * @return 群id或错误
   */
  public static String createPrivateGroup(String owner, String groupName, String description, List<String> members, int maxMembers,
                                          boolean canMemberInvite, String custom) {

    try {
      String groupId = staticEMService.group()
          .createPrivateGroup(owner, groupName, description, members, maxMembers, canMemberInvite,
              custom)
          .block();
      Map<String, Object> ext = new HashMap<>();
      ext.put("data", "创建成功");
      sendCustomMessageToChatGroups(ListUtil.of(groupId), ext);
      return groupId;
    } catch (EMException e) {
      log.error("创建私有群失败code:{}msg:{}", e.getErrorCode(), e.getMessage());
      throw new ServiceException("创建私有群失败");
    }
  }

  /**
   * 创建公有群
   * 公有群可以被搜索到
   *
   * @param owner             群主的用户名  用户id
   * @param groupName         群名，最大长度为 128 字符
   * @param description       群介绍，最大长度为 512 字符
   * @param members           初始群成员的用户名列表  用户id
   * @param maxMembers        群最大成员数
   * @param needApproveToJoin 新成员加入需要管理员审批
   * @param custom            群组扩展信息，例如可以给群组添加业务相关的标记，最大长度为 1024 字符
   * @return 群id或错误
   */
  public static String createPublicGroup(String owner, String groupName, String description, List<String> members, int maxMembers,
                                         boolean needApproveToJoin, String custom) {
    try {
      String groupId = staticEMService.group()
          .createPublicGroup(owner, groupName, description, members, maxMembers, needApproveToJoin,
              custom)
          .block();
      Map<String, Object> ext = new HashMap<>();
      ext.put("data", "创建成功");
      sendCustomMessageToChatGroups(ListUtil.of(groupId), ext);
      return groupId;
    } catch (EMException e) {
      log.error("创建公有群失败code:{}msg:{}", e.getErrorCode(), e.getMessage());
      throw new ServiceException("创建公有群失败");
    }
  }

  /**
   * 注销群
   *
   * @param groupId 群id
   */
  public static void destroyGroup(String groupId) {
    try {
      staticEMService.group().destroyGroup(groupId).block();
    } catch (EMException e) {
      log.error("注销群失败code:{}msg:{}", e.getErrorCode(), e.getMessage());
      throw new ServiceException("注销群失败");
    }
  }

  /**
   * 添加群成员
   *
   * @param groupId     群id
   * @param userIds     用户id
   * @param nickNames   昵称列表  不传则不发入群通知   传的话 没有昵称填充im用户名
   * @param appUserRole 用户角色 {@link UserConstants}
   */
  public static void addGroupMembers(String groupId, List<Long> userIds, List<String> nickNames, String appUserRole) {
    try {

      staticEMService.group()
          .addGroupMembers(groupId, userIds.stream().map(userId -> appUserRole + userId).collect(Collectors.toList())).block();

      if (ObjectUtil.isNotEmpty(nickNames)) {
        for (String nickName : nickNames) {
          Map<String, Object> ext = new HashMap<>();
          ext.put("data", nickName + " 加入群聊");
          sendCustomMessageToChatGroups(ListUtil.of(groupId), ext);
        }
      }
    } catch (EMException e) {
      log.error("添加群成员失败code:{}msg:{}", e.getErrorCode(), e.getMessage());
      throw new ServiceException("添加群成员失败");
    }
  }

  /**
   * 移除群成员(多个)
   *
   * @param groupId     群id
   * @param userIds     用户id
   * @param appUserRole 用户角色 {@link UserConstants}
   */
  public static void removeGroupMembers(String groupId, List<Long> userIds, String appUserRole) {
    try {

      List<EMRemoveMember> removeMembers = staticEMService.group()
          .removeGroupMembers(groupId, userIds.stream().map(userId -> appUserRole + userId).collect(Collectors.toList())).block();
    } catch (EMException e) {
      log.error("移除群成员失败code:{}msg:{}", e.getErrorCode(), e.getMessage());
      throw new ServiceException("移除群成员失败");
    }
  }

  @PostConstruct
  public void init() {
    staticEMService = service;
    staticEMPushService = emPushService;
  }


}
